#ifndef DISPLAYABLE_H
#define DISPLAYABLE_H

#include <vector>
#include <string>
#include <math.h>
#include <SDL/SDL.h>

#include <GL/glew.h>
#include "../tool/vectorf.h"

#include "../tool/delegate.h"
#include "../CollisionDetection/aabb.h"
#include "../CollisionDetection/collision.h"
#include "../actions/action.h"
#include "../actions/velocity.h"

enum GObjectType    //  Enum utilisé pour connaitre le type des objets fils de displayable à l'aide d'un simple test
{
        oRect,
        oRectT
};

/*!
 *  =============================================================================================================
 * 	\class Displayable()
 * 	\brief Classe mère abstraite servant de base aux différents éléments affichable de la scene OpenGL
 *  =============================================================================================================
 */

class Displayable
{
    public :

    /*****************************************************************************************/
    /*                                  Propriétés                                           */
    /*****************************************************************************************/

        int state;
        int collisionIndex;
        int movable;
        int gravity;

        Velocity * velocity;
        Vectorf * barycentre;


        int picking; /*!< Si la valeur est égale à 1, le picking a été défini, sinon 0 */

        SDL_Event * event;      /*!<    Références aux événements SDL   */

        std::vector<AABB *>     aabb;           /*!<    Liste de Bounding Box pouvant être lié à l'objet    */
        std::vector<Action *>   actions;        /*!<    Pile d'actions que l'objet a à exécuter             */
        std::vector<Collision *> collisions;    /*!<    Test de collisions entre objet que le programmeur aura défini   */

        std::vector<AbstractDelegate *> inputDelegates;         /*!<    Délégués gérant les événéments clavier/souris    */
        std::vector<AbstractDelegate *> delegates;              /*!<    Délégués classiques */
        std::vector<AbstractDelegate *> collisionDelegates;     /*!<    Délégué gérant les collisions   */

        GLuint vertexBuffer;    /*!<	Indice du buffer contenant les informations sur les sommets	*/
        GLuint colorBuffer;     /*!<	Indice du buffer utilisé pour stocker les informations de couleurs des sommets	*/
        GLuint indexBuffer;     /*!<	Indice du buffer contenant les informations sur l'indice du sommet à afficher	*/
        GLuint normalBuffer;    /*!<	Indice du buffer utilisé pour stocker les informations concernant les normales des sommets	*/
        GLuint textureBuffer;   /*!<	Indice du buffer utilisé pour stocker les informations concernant les indices de texture des sommets */
        GLuint pickingBuffer;   /*!<    Indice du buffer utilisé pour stocker les informations concernant les couleurs du deuxieme affichage */
        GLuint normalIndiceBuffer;   /*!<    blabla  */

        int dimensionVertex;    /*!<	Nombre de coordoonnées utilisés pour représenter un sommet (compris en 1 et 4)	*/
        int dimensionColors;    /*!<	Nombre de canaux utilisés pour représenter la couleur (entre 1 et 4)	*/
        int dimensionTexture;   /*!<	Nombre dimension utilisés pour représenter la texture (entre 1 et 3)	*/

        unsigned char colorxp;
        unsigned char coloryp;
        unsigned char colorzp;

        unsigned int vertexCount;   /*!<    Nombre de vertex dans le buffer */

        Vectorf * translation;
        Vectorf * rotation;

        int type;               /*!< Identifie le sous-type de l'objet courant (rectangle, sphère etc ...) */

        Vectorf isoBarycentre;  /*!< Coordoonnées du sommet représentant l'isoBarycentre de la forme	*/

    /*****************************************************************************************/
    /*                                  Constructeurs                                        */
    /*****************************************************************************************/

    /*!
     * 	\fn	Displayable(int typeObject)
     * 	\brief	Initialise le type de l'objet dérivé
     *
     * 	\param	int typeObject : type de l'objet : rectangle, rectangle texturé, sprite etc
     */

    Displayable(int typeObject);

    /*!
     * 	\fn	Displayable(int typeObject, Vectorf translation)
     * 	\brief  Initialise le type de l'objet dérivé ainsi que sa position dans la scène openGL via une translation
     *
     * 	\param	int typeObject : type de l'objet : rectangle, rectangle texturé, sprite
     * 	\param 	Vectorf translation : coordonées pour la translation
     */

    Displayable(int,Vectorf translation);

    /*!
     * 	\fn	Displayable(int typeObject, Vectorf translation)
     * 	\brief  Initialise le type de l'objet dérivé ainsi que sa position dans la scène openGL (translation)
     *
     * 	\param	int typeObject : type de l'objet : rectangle, rectangle texturé, sprite
     * 	\param 	Vectorf translation : coordonées pour la translation
     */

    Displayable(int,Vectorf translation, Vectorf rotation);

    virtual ~Displayable();

    /*****************************************************************************************/
    /*                                  Fonctions virtuelles pures                           */
    /*****************************************************************************************/

        /*!
         * 	\fn virtual void Display()=0
         * 	\brief Méthode virtuelle pure utilisé pour afficher les trucs
         */

    virtual void Display()=0;

    /*!
     * 	\fn int SetVertex(int indiceVertex, Vectorf coordinates)
     * 	\brief Méthode permettant de modifier le contenu du buffer
     *
     * 	\param int indiceVertex : Indice du sommet à modifier
     * 	\param Vectorf coordinates : nouvelle coordoonées du sommet
     */

    int SetVertex(int indiceVertex, Vectorf coordinates);

    /*!
     * 	\fn Vectorf GetVertex(int indiceVertex)
     * 	\brief Méthode permettant récupérer les coordonnées d'un sommet
     *
     * 	\param int indiceVertex : Indice du sommet à récupérer
     */

    Vectorf GetVertex(int indiceVertex);

    /*!
     * 	\fn	int SetColor(int indiceColor, Vectorf color)
     *	\brief	Méthode permettant de modifier la couleur d'un sommet
     */

    int SetColor(int indiceColor, Vectorf);

    /*!
     * 	\fn Vectorf GetColor(int indiceColor)
     * 	\brief Méthode permettant récupérer les composantes RGB
     *
     * 	\param int indiceVertex : Indice du sommet à récupérer
     */

    void Update();

    virtual void Picking()=0;

    Vectorf GetColor(int indiceColor);

    virtual void SetPicking(unsigned char x, unsigned char y , unsigned char z)=0;


    int SetTexture(int indiceVertex, Vectorf);

    Vectorf pickingColor;
    Vectorf GetTexture();

    void CheckDelegates();
    void CheckInputDelegates();

    AABB * SetAABB();
    void SetMovable(Vectorf * vec);
    float valGravity;

};
#endif // DISPLAYABLE_H
